<?php
function cmi($connomains,$killspace=TRUE,$forhtml=TRUE,$timeout=6,$header=0,$follow=1){
     /*
      cmi该函数的目的在于并发请求多个url，然后返回<a href="http://www.trackself.com/" target="_blank">http://www.trackself.com</a>编写,真正的PHP并发
      原文发表在<a href="http://www.trackself.com/archives/463.html">http://www.trackself.com/archives/463.html</a>
      此并发请求在url多于2的时候，明显比for ... file_get_contents ...要优很多
      核心是curl库的curl_multi方法
      用法：
      $urls=array(
                  'http://www.google.com',
                  'http://www.baidu.com',
                  'http://sina.com',
                  'http://163.com'
                  )
      $htmls=cmi($urls);
      print_r($htmls);

        //传入的$connomains是URL一维数组，由http://www.trackself.com编写
      //该函数的目的在于并发请求多个url，然后返回源码
      //以一次性略增加CPU为代价
      //来减轻服务器因为for ... file_get_contents ...的长时连接负担及内存和CPU的负担，所以并发数不要大多（50以内效果非常好），尽量不要用于单页面或3页面以内的请求	
      //$killspace为真时表示自动去掉HTML中换行及多余的空白，$forhtml为真时表示反回源码，为faluse时就是并发执行请求了（可以用于计划任务）
      //后面的几个参数的详细说明请看注释，毕竟函数不长
      */

    $res=array();
    $urlsa=array();
    $results=array();
    $mh = curl_multi_init();//创建多curl对象，为了几乎同时执行		
    foreach ($connomains as $i =&gt; $url) {
        $conn[$i]=curl_init($url);//若url中含有gb2312汉字，例如FTP时，要在传入url的时候处理一下，这里不用
        curl_setopt($conn[$i], CURLOPT_TIMEOUT, $timeout);//此时间须根据页面的HTML源码出来的时间，一般是在1s内的，慢的话应该也不会6秒，极慢则是在16秒内
        curl_setopt($conn[$i], CURLOPT_HEADER, $header);//不返回请求头，只要源码
        curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1);//必须为1
        curl_setopt($conn[$i], CURLOPT_FOLLOWLOCATION, $follow);//如果页面含有自动跳转的代码如301或者302HTTP时，自动拿转向的页面
        curl_multi_add_handle ($mh,$conn[$i]);//关键，一定要放在上面几句之下，将单curl对象赋给多对象
    }
    //下面一大步的目的是为了减少cpu的无谓负担，暂时不明，来自php.net的建议，几乎是固定用法
    do {
        $mrc = curl_multi_exec($mh,$active);//当无数据时或请求暂停时，active=true
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);//当正在接受数据时
    while ($active and $mrc == CURLM_OK) {//当无数据时或请求暂停时，active=true,为了减少cpu的无谓负担,这一步很难明啊
        if (curl_multi_select($mh) != -1) {
            do {
                $mrc = curl_multi_exec($mh, $active);
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        }
    }
    /////////////////////////////////////////////////////////////////////////////////////////
    //下面返回结果
    foreach ($connomains as $i =&gt; $url) {
        $cinfo=curl_getinfo($conn[$i]);//可用于取得一些有用的参数，可以认为是header
        $url=$cinfo[url];//真实url,有些url
        if($killspace){//有点水消耗
            $str=trim(curl_multi_getcontent($conn[$i]));
            $str = preg_replace('/\s(?=\s)/', '', $str);//去掉跟随别的挤在一块的空白   	    
            $str = preg_replace('/[\n\r\t]/', ' ', $str);  //最后，去掉非space 的空白，用一个空格代替
            $res[$i]=stripslashes($str);//取得对象源码，并取消换行，节约内存的同时，可以方便作正则处理
        }else{
            $res[$i]=curl_multi_getcontent($conn[$i]);
        }
        if(!$forhtml){//节约内存			
            $res[$i]=NULL;
        }
                 /*下面这一段放一些高消耗的程序代码，用来处理HTML，我保留的一句=NULL是要提醒，及时清空对象释放内存，此程序在并发过程中如果源码太大，内在消耗严重
                 //事实上，这里应该做一个callback函数或者你应该将你的逻辑直接放到这里来，我为了程序可重复，没这么做
                   preg_match_all($preg,$res[$i],$matchlinks);
                   $res[$i]=NULL;
                  */   
        curl_close($conn[$i]);//关闭所有对象
        curl_multi_remove_handle($mh  , $conn[$i]);   //用完马上释放资源           			   

    } 
    curl_multi_close($mh);$mh=NULL;$conn=NULL;

    return $res;
}//cmi

function cmi($connomains,$killspace=TRUE,$forhtml=TRUE,$timeout=6,$header=0,$follow=1){
     /*
      cmi该函数的目的在于并发请求多个url，然后返回<a href="http://www.trackself.com/" target="_blank">http://www.trackself.com</a>编写,真正的PHP并发
      原文发表在<a href="http://www.trackself.com/archives/463.html">http://www.trackself.com/archives/463.html</a>
      此并发请求在url多于2的时候，明显比for ... file_get_contents ...要优很多
      核心是curl库的curl_multi方法
      用法：
      //array_flip(array_flip($connomains))
      $urls=array(
                  'http://www.google.com',
                  'http://www.baidu.com',
                  'http://sina.com',
                  'http://163.com'
                  )
      $urls=array_flip(array_flip($connomains));//去除url中的重复的项，注意传入urls时一定要系合法的url表达，虽然不会影响其它url执行，但会减慢执行速度
      $htmls=cmi($urls);
      print_r($htmls);

        //传入的$connomains是URL一维数组，由http://www.trackself.com编写
      //该函数的目的在于并发请求多个url，然后返回源码
      //以一次性略增加CPU为代价
      //来减轻服务器因为for ... file_get_contents ...的长时连接负担及内存和CPU的负担，所以并发数不要大多（50以内效果非常好），尽量不要用于单页面或3页面以内的请求	
      //$killspace为真时表示自动去掉HTML中换行及多余的空白，$forhtml为真时表示反回源码，为faluse时就是并发执行请求了（可以用于计划任务）
      //后面的几个参数的详细说明请看注释，毕竟函数不长
      */

    $res=array();//用于保存结果 	    	
    //$connomains=array_flip(array_flip($connomains));//去除url中的重复项
    $mh = curl_multi_init();//创建多curl对象，为了几乎同时执行		
    foreach ($connomains as $i =&gt; $url) {
        $conn[$url]=curl_init($url);//若url中含有gb2312汉字，例如FTP时，要在传入url的时候处理一下，这里不用
        curl_setopt($conn[$url], CURLOPT_TIMEOUT, $timeout);//此时间须根据页面的HTML源码出来的时间，一般是在1s内的，慢的话应该也不会6秒，极慢则是在16秒内
        curl_setopt($conn[$url], CURLOPT_HEADER, $header);//不返回请求头，只要源码
        curl_setopt($conn[$url],CURLOPT_RETURNTRANSFER,1);//必须为1
        curl_setopt($conn[$url], CURLOPT_FOLLOWLOCATION, $follow);//如果页面含有自动跳转的代码如301或者302HTTP时，自动拿转向的页面
        curl_multi_add_handle ($mh,$conn[$url]);//关键，一定要放在上面几句之下，将单curl对象赋给多对象
    }
    //下面一大步的目的是为了减少cpu的无谓负担，暂时不明，来自php.net的建议，几乎是固定用法
    do {
        $mrc = curl_multi_exec($mh,$active);//当无数据时或请求暂停时，active=true
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);//当正在接受数据时
    while ($active and $mrc == CURLM_OK) {//当无数据时或请求暂停时，active=true,为了减少cpu的无谓负担,这一步很难明啊
        if (curl_multi_select($mh) != -1) {
            do {
                $mrc = curl_multi_exec($mh, $active);
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        }
    }
    /////////////////////////////////////////////////////////////////////////////////////////
    //下面返回结果
    foreach ($connomains as $i =&gt; $url) {
        $cinfo=curl_getinfo($conn[$url]);//可用于取得一些有用的参数，可以认为是header
        //$url=$cinfo[url];//真实url,有些url
        if($killspace){//有点水消耗
            $str=trim(curl_multi_getcontent($conn[$url]));
            $str = preg_replace('/\s(?=\s)/', '', $str);//去掉跟随别的挤在一块的空白   	    
            $str = preg_replace('/[\n\r\t]/', ' ', $str);  //最后，去掉非space 的空白，用一个空格代替
            $res[$url]=stripslashes($str);//取得对象源码，并取消换行，节约内存的同时，可以方便作正则处理
        }else{
            $res[$url]=curl_multi_getcontent($conn[$url]);
        }
        if(!$forhtml){//节约内存			
            $res[$url]=NULL;
        }
                 /*下面这一段放一些高消耗的程序代码，用来处理HTML，我保留的一句=NULL是要提醒，及时清空对象释放内存，此程序在并发过程中如果源码太大，内在消耗严重
                 //事实上，这里应该做一个callback函数或者你应该将你的逻辑直接放到这里来，我为了程序可重复，没这么做
                   preg_match_all($preg,$res[$i],$matchlinks);
                   $res[$i]=NULL;
                  */  
        curl_close($conn[$url]);//关闭所有对象 
        curl_multi_remove_handle($mh  , $conn[$url]);   //用完马上释放资源           			   

    } 
    curl_multi_close($mh);$mh=NULL;$conn=NULL;$connomains=NULL;

    return $res;
}//cmi
